/*     */ package com.zimbra.cs.service.formatter;
/*     */ 
/*     */ import com.google.common.base.Strings;
/*     */ import com.zimbra.common.mailbox.ContactConstants;
/*     */ import com.zimbra.common.service.ServiceException;
/*     */ import com.zimbra.common.util.DateUtil;
/*     */ import com.zimbra.common.util.Log;
/*     */ import com.zimbra.common.util.ZimbraLog;
/*     */ import com.zimbra.cs.mailbox.Contact;
/*     */ import com.zimbra.cs.mailbox.Contact.Attachment;
/*     */ import com.zimbra.cs.mailbox.Contact.DerefGroupMembersOption;
/*     */ import com.zimbra.cs.mailbox.Mailbox;
/*     */ import com.zimbra.cs.mime.ParsedContact;
/*     */ import com.zimbra.cs.util.Zimbra;
/*     */ import java.text.SimpleDateFormat;
/*     */ import java.util.ArrayList;
/*     */ import java.util.Arrays;
/*     */ import java.util.Collection;
/*     */ import java.util.Date;
/*     */ import java.util.HashMap;
/*     */ import java.util.HashSet;
/*     */ import java.util.List;
/*     */ import java.util.Map;
/*     */ import java.util.Map.Entry;
/*     */ import java.util.Set;
/*     */ import javax.mail.internet.ContentType;
/*     */ import javax.mail.internet.ParseException;
/*     */ import org.apache.commons.codec.binary.Base64;
/*     */ import org.apache.commons.codec.net.QuotedPrintableCodec;
/*     */ import org.json.JSONException;
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ public class VCard
/*     */ {
/*     */   public String uid;
/*     */   public String fn;
/*     */   private final String formatted;
/*     */   public Map<String, String> fields;
/*     */   public List<Contact.Attachment> attachments;
/*     */   
/*     */   private VCard(String xfn, String xformatted, Map<String, String> xfields, List<Contact.Attachment> xattachments, String xuid)
/*     */   {
/*  59 */     this.fn = xfn;this.formatted = xformatted;this.fields = xfields;this.attachments = xattachments;this.uid = xuid;
/*     */   }
/*     */   
/*     */   public ParsedContact asParsedContact() throws ServiceException {
/*  63 */     return new ParsedContact(this.fields, this.attachments);
/*     */   }
/*     */   
/*     */ 
/*  67 */   private static final Set<String> PROPERTY_NAMES = new HashSet(Arrays.asList(new String[] { "BEGIN", "FN", "N", "NICKNAME", "PHOTO", "KEY", "BDAY", "ADR", "TEL", "EMAIL", "URL", "ORG", "TITLE", "NOTE", "AGENT", "END", "UID", "X-ZIMBRA-IMADDRESS1", "X-ZIMBRA-IMADDRESS2", "X-ZIMBRA-IMADDRESS3", "X-ZIMBRA-ANNIVERSARY", "X-ZIMBRA-MAIDENNAME" }));
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*  93 */   static final Map<String, String> PARAM_ABBREVIATIONS = new HashMap();
/*     */   
/*  95 */   static { PARAM_ABBREVIATIONS.put("BASE64", "ENCODING=B");
/*  96 */     PARAM_ABBREVIATIONS.put("QUOTED-PRINTABLE", "ENCODING=QUOTED-PRINTABLE");
/*  97 */     PARAM_ABBREVIATIONS.put("HOME", "TYPE=HOME");
/*  98 */     PARAM_ABBREVIATIONS.put("WORK", "TYPE=WORK");
/*  99 */     PARAM_ABBREVIATIONS.put("FAX", "TYPE=FAX");
/* 100 */     PARAM_ABBREVIATIONS.put("CELL", "TYPE=CELL");
/* 101 */     PARAM_ABBREVIATIONS.put("PAGER", "TYPE=PAGER");
/* 102 */     PARAM_ABBREVIATIONS.put("CAR", "TYPE=CAR");
/*     */   }
/*     */   
/* 105 */   private static enum Encoding { NONE,  B,  Q;
/*     */     
/*     */     private Encoding() {} }
/*     */   
/*     */   private static class VCardProperty { private String group;
/* 110 */     private String name; private final Set<String> params = new HashSet();
/*     */     private String charset;
/* 112 */     private VCard.Encoding encoding = VCard.Encoding.NONE;
/*     */     private String value;
/*     */     private boolean isEmpty;
/*     */     
/* 116 */     boolean isEmpty() { return this.isEmpty; }
/* 117 */     VCard.Encoding getEncoding() { return this.encoding; }
/* 118 */     boolean containsParam(String param) { return this.params.contains(param); }
/*     */     
/* 120 */     String getParamValue(String pname) { pname = pname.toUpperCase() + '=';
/* 121 */       for (String param : this.params) {
/* 122 */         if (param.startsWith(pname)) {
/* 123 */           return param.substring(pname.length());
/*     */         }
/*     */       }
/* 126 */       return null;
/*     */     }
/*     */     
/*     */     private void reset() {
/* 130 */       this.group = (this.name = this.value = null);
/* 131 */       this.charset = "utf-8";
/* 132 */       this.params.clear();
/* 133 */       this.encoding = VCard.Encoding.NONE;
/* 134 */       this.isEmpty = false;
/*     */     }
/*     */     
/*     */     String parse(StringBuilder line) throws ServiceException {
/* 138 */       reset();
/* 139 */       this.isEmpty = VCard.isAllWhitespace(line);
/* 140 */       if (this.isEmpty) {
/* 141 */         return "";
/*     */       }
/*     */       
/*     */ 
/* 145 */       int colon = line.indexOf(":");
/* 146 */       if (colon == -1) {
/* 147 */         throw ServiceException.PARSE_ERROR("missing ':' in line " + VCard.shortFormForLogging(line), null);
/*     */       }
/* 149 */       this.value = line.substring(colon + 1);
/*     */       
/*     */ 
/*     */ 
/* 153 */       char c = '\000';
/* 154 */       int start; for (int i = start = 0; i < colon; i++) {
/* 155 */         if ((c = line.charAt(i)) == '.')
/* 156 */           start = i + 1; else {
/* 157 */           if (c == ';')
/*     */             break;
/*     */         }
/*     */       }
/* 161 */       if (start != 0) {
/* 162 */         this.group = line.substring(0, start - 1);
/*     */       }
/* 164 */       this.name = line.substring(start, i).trim().toUpperCase();
/*     */       
/*     */ 
/* 167 */       String pname = null;
/* 168 */       while (i < colon) {
/* 169 */         i++; for (start = i; i < colon; i++) {
/* 170 */           if (((c = line.charAt(i)) == ';') || (
/* 171 */             (c == ',') && (pname != null))) break;
/* 172 */           if ((c == '=') && (pname == null) && (i > start)) {
/* 173 */             pname = line.substring(start, i).toUpperCase();
/* 174 */             start = i + 1;
/*     */           }
/*     */         }
/* 177 */         String pval = line.substring(start, i).toUpperCase();
/* 178 */         if (!pval.equals("")) {
/* 179 */           String param = pname != null ? pname + '=' + pval : (String)VCard.PARAM_ABBREVIATIONS.get(pval);
/* 180 */           if (param == null) continue;
/* 181 */           if (param.equals("ENCODING=B")) { this.encoding = VCard.Encoding.B;
/* 182 */           } else if (param.equals("ENCODING=BASE64")) { this.encoding = VCard.Encoding.B;
/* 183 */           } else if (param.equals("ENCODING=QUOTED-PRINTABLE")) { this.encoding = VCard.Encoding.Q;
/* 184 */           } else if ((pname != null) && (pname.equals("CHARSET"))) this.charset = pval; else {
/* 185 */             this.params.add(param);
/*     */           }
/*     */         }
/* 188 */         if (c == ';') {
/* 189 */           pname = null;
/*     */         }
/*     */       }
/* 192 */       return this.name;
/*     */     }
/*     */     
/*     */     String getGroup() {
/* 196 */       return this.group;
/*     */     }
/*     */     
/*     */     String getValue()
/*     */     {
/*     */       try {
/* 202 */         if (this.encoding == VCard.Encoding.B) {
/* 203 */           byte[] encoded = this.value.getBytes();
/* 204 */           if (Base64.isBase64(encoded))
/* 205 */             this.value = new String(Base64.decodeBase64(encoded), this.charset);
/* 206 */         } else if (this.encoding == VCard.Encoding.Q) {
/* 207 */           this.value = new QuotedPrintableCodec(this.charset).decode(this.value);
/*     */         }
/* 209 */         this.encoding = VCard.Encoding.NONE;
/*     */       } catch (Exception ignored) {}
/* 211 */       return this.value;
/*     */     }
/*     */     
/*     */     byte[] getDecoded() {
/* 215 */       byte[] encoded = this.value.getBytes();
/*     */       try {
/* 217 */         if ((this.encoding == VCard.Encoding.B) && (Base64.isBase64(encoded)))
/* 218 */           encoded = Base64.decodeBase64(encoded);
/* 219 */         this.encoding = VCard.Encoding.NONE;
/*     */       } catch (Exception ignored) {}
/* 221 */       return encoded;
/*     */     }
/*     */   }
/*     */   
/*     */   public static List<VCard> parseVCard(String vcard) throws ServiceException {
/* 226 */     List<VCard> cards = new ArrayList();
/*     */     
/* 228 */     Map<String, String> fields = new HashMap();
/* 229 */     Map<String, Object> xprops = new HashMap();
/* 230 */     List<Contact.Attachment> attachments = new ArrayList();
/*     */     
/* 232 */     VCardProperty vcprop = new VCardProperty(null);
/* 233 */     int depth = 0;
/* 234 */     int cardstart = 0;
/* 235 */     String uid = null;
/* 236 */     StringBuilder line = new StringBuilder(256);
/* 237 */     int pos = 0; for (int limit = vcard.length(); pos < limit;)
/*     */     {
/* 239 */       line.setLength(0);
/* 240 */       String name = null;
/*     */       
/* 242 */       int linestart = pos;
/* 243 */       boolean folded = true;
/*     */       do {
/* 245 */         int start = pos;
/* 246 */         while ((pos < limit) && (vcard.charAt(pos) != '\r') && (vcard.charAt(pos) != '\n')) {
/* 247 */           pos++;
/*     */         }
/* 249 */         line.append(vcard.substring(start, pos));
/* 250 */         if (pos < limit) {
/* 251 */           if ((pos < limit) && (vcard.charAt(pos) == '\r')) pos++;
/* 252 */           if ((pos < limit) && (vcard.charAt(pos) == '\n')) pos++;
/*     */         }
/* 254 */         if ((pos < limit) && ((vcard.charAt(pos) == ' ') || (vcard.charAt(pos) == '\t'))) {
/* 255 */           pos++;
/*     */         } else {
/* 257 */           name = vcprop.parse(line);
/* 258 */           if ((vcprop.getEncoding() != Encoding.Q) || (line.length() <= 0) || ('=' != line.charAt(line.length() - 1)))
/*     */           {
/* 260 */             folded = false;
/*     */           }
/*     */         }
/* 263 */       } while (folded);
/* 264 */       if (!vcprop.isEmpty())
/*     */       {
/*     */ 
/* 267 */         if (Strings.isNullOrEmpty(name))
/* 268 */           throw ServiceException.PARSE_ERROR("missing property name in line " + shortFormForLogging(line), null);
/* 269 */         if ((name.startsWith("X-")) && (!name.startsWith("X-ZIMBRA-"))) {
/* 270 */           String decodedValue = vcfDecode(vcprop.getValue());
/*     */           
/* 272 */           String group = vcprop.getGroup();
/* 273 */           String key = group + "." + name;
/* 274 */           Object val = xprops.get(key);
/* 275 */           if (val != null) {
/* 276 */             if ((val instanceof ArrayList))
/*     */             {
/* 278 */               ArrayList<String> valArray = (ArrayList)val;
/* 279 */               valArray.add(decodedValue);
/*     */             } else {
/* 281 */               ArrayList<String> valArray = new ArrayList();
/* 282 */               valArray.add((String)val);
/* 283 */               valArray.add(decodedValue);
/* 284 */               xprops.put(key, valArray);
/*     */             }
/*     */           } else
/* 287 */             xprops.put(key, decodedValue);
/*     */         } else {
/* 289 */           if (!PROPERTY_NAMES.contains(name))
/*     */             continue;
/* 291 */           if (name.equals("BEGIN")) {
/* 292 */             depth++; if (depth != 1)
/*     */               continue;
/* 294 */             fields = new HashMap();
/* 295 */             xprops = new HashMap();
/* 296 */             attachments = new ArrayList();
/* 297 */             cardstart = linestart;
/* 298 */             uid = null; continue;
/*     */           }
/*     */           
/* 301 */           if (name.equals("END")) {
/* 302 */             if ((depth <= 0) || (depth-- != 1)) continue;
/* 303 */             if (!xprops.isEmpty()) {
/* 304 */               HashMap<String, String> newMap = new HashMap();
/*     */               
/* 306 */               for (Map.Entry<String, Object> xprop : xprops.entrySet()) {
/* 307 */                 Object v = xprop.getValue();
/* 308 */                 String val = null;
/* 309 */                 if ((v instanceof ArrayList))
/*     */                 {
/* 311 */                   ArrayList<String> valArray = (ArrayList)v;
/*     */                   try {
/* 313 */                     val = Contact.encodeMultiValueAttr((String[])valArray.toArray(new String[valArray.size()]));
/*     */                   }
/*     */                   catch (JSONException ignored) {}
/* 316 */                   if (val == null)
/* 317 */                     val = v.toString();
/* 318 */                   newMap.put(xprop.getKey(), val);
/*     */                 } else {
/* 320 */                   newMap.put(xprop.getKey(), (String)v);
/*     */                 }
/*     */               }
/* 323 */               fields.put("vcardXProps", Contact.encodeXProps(newMap));
/*     */             }
/*     */             
/*     */ 
/* 327 */             if (fields.isEmpty()) continue;
/* 328 */             Contact.normalizeFileAs(fields);
/* 329 */             cards.add(new VCard((String)fields.get(ContactConstants.A_fullName), vcard.substring(cardstart, pos), fields, attachments, uid)); continue;
/*     */           }
/*     */           
/*     */ 
/* 333 */           if (depth <= 0)
/*     */             continue;
/* 335 */           if (name.equals("AGENT"))
/*     */           {
/* 337 */             if (!vcprop.getValue().trim().toUpperCase().matches("BEGIN\\s*:\\s*VCARD")) continue;
/* 338 */             depth++; continue;
/*     */           }
/*     */         }
/*     */         
/* 342 */         if ((vcprop.getEncoding() == Encoding.B) && (!vcprop.containsParam("VALUE=URI"))) {
/* 343 */           if (name.equals("PHOTO")) {
/* 344 */             String suffix = vcprop.getParamValue("TYPE");String ctype = null;
/* 345 */             if ((suffix != null) && (!suffix.equals(""))) {
/* 346 */               ctype = "image/" + suffix.toLowerCase();
/* 347 */               suffix = '.' + suffix;
/*     */             }
/* 349 */             attachments.add(new Contact.Attachment(vcprop.getDecoded(), ctype, "image", "image" + suffix));
/* 350 */             continue;
/*     */           }
/* 352 */           if (name.equals("KEY")) {
/* 353 */             String encoded = new String(Base64.encodeBase64Chunked(vcprop.getDecoded()));
/* 354 */             fields.put(ContactConstants.A_userCertificate, encoded);
/* 355 */             continue;
/*     */           }
/*     */         }
/*     */         
/* 359 */         String value = vcprop.getValue();
/*     */         
/*     */ 
/* 362 */         if (name.equals("FN")) { addField(ContactConstants.A_fullName, vcfDecode(value), "altFullName", 2, fields);
/* 363 */         } else if (name.equals("N")) { decodeStructured(value, NAME_FIELDS, fields);
/* 364 */         } else if (name.equals("NICKNAME"))
/*     */         {
/* 366 */           addField(ContactConstants.A_nickname, vcfDecode(value), "altNickName", 2, fields);
/* 367 */         } else if (name.equals("PHOTO")) { fields.put(ContactConstants.A_image, vcfDecode(value));
/* 368 */         } else if (name.equals("BDAY")) { addField(ContactConstants.A_birthday, vcfDecode(value), null, 2, fields);
/* 369 */         } else if (name.equals("ADR")) { decodeAddress(value, vcprop, fields);
/* 370 */         } else if (name.equals("TEL")) { decodeTelephone(value, vcprop, fields);
/* 371 */         } else if (name.equals("URL")) { decodeURL(value, vcprop, fields);
/* 372 */         } else if (name.equals("ORG")) { decodeStructured(value, ORG_FIELDS, fields);
/* 373 */         } else if (name.equals("TITLE")) { addField(ContactConstants.A_jobTitle, vcfDecode(value), "altJobTitle", 2, fields);
/* 374 */         } else if (name.equals("NOTE")) { addField(ContactConstants.A_notes, vcfDecode(value), null, 2, fields);
/* 375 */         } else if (name.equals("EMAIL")) { addField(ContactConstants.A_email, vcfDecode(value), null, 2, fields);
/* 376 */         } else if (name.equals("X-ZIMBRA-MAIDENNAME")) { fields.put(ContactConstants.A_maidenName, vcfDecode(value));
/* 377 */         } else if (name.startsWith("X-ZIMBRA-IMADDRESS")) { addField("imAddress", true, vcfDecode(value), null, 1, fields);
/* 378 */         } else if (name.equals("X-ZIMBRA-ANNIVERSARY")) { addField(ContactConstants.A_anniversary, vcfDecode(value), null, 2, fields);
/* 379 */         } else if (name.equals("UID")) uid = value;
/*     */       }
/*     */     }
/* 382 */     return cards;
/*     */   }
/*     */   
/*     */   static String shortFormForLogging(StringBuilder line) {
/* 386 */     if (line.length() <= 70) {
/* 387 */       return line.toString();
/*     */     }
/* 389 */     return line.substring(0, 70) + "...";
/*     */   }
/*     */   
/*     */   static boolean isAllWhitespace(StringBuilder line)
/*     */   {
/* 394 */     int length = line.length();
/* 395 */     for (int ndx = 0; ndx < length; ndx++) {
/* 396 */       if (!Character.isWhitespace(line.charAt(ndx))) {
/* 397 */         return false;
/*     */       }
/*     */     }
/* 400 */     return true;
/*     */   }
/*     */   
/*     */   private static void removeField(String firstKey, boolean skipFirstKey, int firstSuffix, Map<String, String> fields) {
/* 404 */     if (!skipFirstKey) {
/* 405 */       fields.remove(firstKey);
/*     */     }
/* 407 */     for (int suffix = firstSuffix; suffix < 20; suffix++) {
/* 408 */       String trialKey = firstKey + String.valueOf(suffix);
/* 409 */       if (fields.remove(trialKey) == null) {
/*     */         break;
/*     */       }
/*     */     }
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */   private static void removeVCardFields(Map<String, String> fields)
/*     */   {
/* 420 */     fields.remove(ContactConstants.A_fullName);
/* 421 */     fields.remove(ContactConstants.A_company);
/* 422 */     fields.remove(ContactConstants.A_lastName);
/* 423 */     fields.remove(ContactConstants.A_firstName);
/* 424 */     fields.remove(ContactConstants.A_middleName);
/* 425 */     fields.remove(ContactConstants.A_namePrefix);
/* 426 */     fields.remove(ContactConstants.A_nameSuffix);
/* 427 */     fields.remove(ContactConstants.A_nickname);
/* 428 */     fields.remove(ContactConstants.A_image);
/* 429 */     fields.remove(ContactConstants.A_birthday);
/* 430 */     fields.remove(ContactConstants.A_company);
/* 431 */     fields.remove(ContactConstants.A_department);
/* 432 */     fields.remove(ContactConstants.A_jobTitle);
/* 433 */     fields.remove(ContactConstants.A_notes);
/* 434 */     fields.remove(ContactConstants.A_type);
/* 435 */     fields.remove(ContactConstants.A_groupMember);
/* 436 */     fields.remove("vcardXProps");
/*     */     
/* 438 */     removeField(ContactConstants.A_homeStreet, false, 2, fields);
/* 439 */     removeField(ContactConstants.A_homeCity, false, 2, fields);
/* 440 */     removeField(ContactConstants.A_homeState, false, 2, fields);
/* 441 */     removeField(ContactConstants.A_homePostalCode, false, 2, fields);
/* 442 */     removeField(ContactConstants.A_homeCountry, false, 2, fields);
/* 443 */     removeField(ContactConstants.A_workStreet, false, 2, fields);
/* 444 */     removeField(ContactConstants.A_workCity, false, 2, fields);
/* 445 */     removeField(ContactConstants.A_workState, false, 2, fields);
/* 446 */     removeField(ContactConstants.A_workPostalCode, false, 2, fields);
/* 447 */     removeField(ContactConstants.A_workCountry, false, 2, fields);
/* 448 */     removeField(ContactConstants.A_otherStreet, false, 2, fields);
/* 449 */     removeField(ContactConstants.A_otherCity, false, 2, fields);
/* 450 */     removeField(ContactConstants.A_otherState, false, 2, fields);
/* 451 */     removeField(ContactConstants.A_otherPostalCode, false, 2, fields);
/* 452 */     removeField(ContactConstants.A_otherCountry, false, 2, fields);
/*     */     
/* 454 */     removeField(ContactConstants.A_carPhone, false, 2, fields);
/* 455 */     removeField(ContactConstants.A_homeFax, false, 2, fields);
/* 456 */     removeField(ContactConstants.A_homePhone, false, 2, fields);
/* 457 */     removeField(ContactConstants.A_mobilePhone, false, 2, fields);
/* 458 */     removeField(ContactConstants.A_otherFax, false, 2, fields);
/* 459 */     removeField(ContactConstants.A_otherPhone, false, 2, fields);
/* 460 */     removeField(ContactConstants.A_pager, false, 2, fields);
/* 461 */     removeField(ContactConstants.A_workFax, false, 2, fields);
/* 462 */     removeField(ContactConstants.A_workPhone, false, 2, fields);
/* 463 */     removeField(ContactConstants.A_email, false, 2, fields);
/*     */     
/* 465 */     removeField(ContactConstants.A_homeURL, false, 2, fields);
/* 466 */     removeField(ContactConstants.A_otherURL, false, 2, fields);
/* 467 */     removeField(ContactConstants.A_workURL, false, 2, fields);
/*     */     
/* 469 */     removeField("workEmail", true, 1, fields);
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */   public void merge(Contact existingContact)
/*     */   {
/* 477 */     Map<String, String> existingFields = existingContact.getAllFields();
/* 478 */     removeVCardFields(existingFields);
/* 479 */     for (Map.Entry<String, String> entry : existingFields.entrySet()) {
/* 480 */       if (!this.fields.containsKey(entry.getKey())) {
/* 481 */         this.fields.put(entry.getKey(), entry.getValue());
/*     */       }
/*     */     }
/*     */   }
/*     */   
/*     */   private static void addField(String firstKey, String value, String customPrefix, int firstSuffix, Map<String, String> fields)
/*     */   {
/* 488 */     addField(firstKey, false, value, customPrefix, firstSuffix, fields);
/*     */   }
/*     */   
/*     */   private static void addField(String firstKey, boolean skipFirstKey, String value, String customPrefix, int firstSuffix, Map<String, String> fields)
/*     */   {
/* 493 */     if ((!skipFirstKey) && (!fields.containsKey(firstKey))) {
/* 494 */       fields.put(firstKey, value);
/*     */     } else {
/* 496 */       if (customPrefix == null) customPrefix = firstKey;
/* 497 */       for (int suffix = firstSuffix; suffix < 20; suffix++) {
/* 498 */         String trialKey = customPrefix + String.valueOf(suffix);
/* 499 */         if (!fields.containsKey(trialKey)) {
/* 500 */           fields.put(trialKey, value);
/* 501 */           break;
/*     */         }
/*     */       }
/*     */     }
/*     */   }
/*     */   
/*     */   private static void decodeTelephone(String value, VCardProperty vcprop, Map<String, String> fields) {
/* 508 */     value = vcfDecode(value);
/* 509 */     if (vcprop.containsParam("TYPE=CAR")) { addField(ContactConstants.A_carPhone, value, null, 2, fields);return; }
/* 510 */     if (vcprop.containsParam("TYPE=CELL")) { addField(ContactConstants.A_mobilePhone, value, null, 2, fields);return; }
/* 511 */     if (vcprop.containsParam("TYPE=PAGER")) { addField(ContactConstants.A_pager, value, null, 2, fields);return;
/*     */     }
/* 513 */     boolean home = vcprop.containsParam("TYPE=HOME");boolean work = vcprop.containsParam("TYPE=WORK");
/* 514 */     boolean fax = vcprop.containsParam("TYPE=FAX");boolean voice = vcprop.containsParam("TYPE=VOICE");
/* 515 */     if (home) {
/* 516 */       if (fax) addField(ContactConstants.A_homeFax, value, null, 2, fields);
/* 517 */       if ((voice) || (!fax)) addField(ContactConstants.A_homePhone, value, null, 2, fields);
/*     */     }
/* 519 */     if (work) {
/* 520 */       if (fax) addField(ContactConstants.A_workFax, value, null, 2, fields);
/* 521 */       if ((voice) || (!fax)) addField(ContactConstants.A_workPhone, value, null, 2, fields);
/*     */     }
/* 523 */     if ((!home) && (!work)) {
/* 524 */       if (fax) addField(ContactConstants.A_otherFax, value, null, 2, fields);
/* 525 */       if ((voice) || (!fax)) addField(ContactConstants.A_otherPhone, value, null, 2, fields);
/*     */     }
/*     */   }
/*     */   
/*     */   private static void decodeAddress(String value, VCardProperty vcprop, Map<String, String> fields) {
/* 530 */     boolean home = vcprop.containsParam("TYPE=HOME");boolean work = vcprop.containsParam("TYPE=WORK");
/* 531 */     if (home) decodeStructured(value, ADR_HOME_FIELDS, fields);
/* 532 */     if (work) decodeStructured(value, ADR_WORK_FIELDS, fields);
/* 533 */     if ((!home) && (!work)) decodeStructured(value, ADR_OTHER_FIELDS, fields);
/*     */   }
/*     */   
/*     */   private static void decodeURL(String value, VCardProperty vcprop, Map<String, String> fields) {
/* 537 */     boolean home = vcprop.containsParam("TYPE=HOME");boolean work = vcprop.containsParam("TYPE=WORK");
/* 538 */     if (home) addField(ContactConstants.A_homeURL, value, null, 2, fields);
/* 539 */     if (work) addField(ContactConstants.A_workURL, value, null, 2, fields);
/* 540 */     if ((!home) && (!work)) addField(ContactConstants.A_otherURL, value, null, 2, fields);
/*     */   }
/*     */   
/* 543 */   private static final String[] NAME_FIELDS = { ContactConstants.A_lastName, ContactConstants.A_firstName, ContactConstants.A_middleName, ContactConstants.A_namePrefix, ContactConstants.A_nameSuffix };
/*     */   
/*     */ 
/* 546 */   private static final String[] ADR_HOME_FIELDS = { ContactConstants.A_homeStreet, ContactConstants.A_homeStreet, ContactConstants.A_homeStreet, ContactConstants.A_homeCity, ContactConstants.A_homeState, ContactConstants.A_homePostalCode, ContactConstants.A_homeCountry };
/*     */   
/*     */ 
/*     */ 
/* 550 */   private static final String[] ADR_WORK_FIELDS = { ContactConstants.A_workStreet, ContactConstants.A_workStreet, ContactConstants.A_workStreet, ContactConstants.A_workCity, ContactConstants.A_workState, ContactConstants.A_workPostalCode, ContactConstants.A_workCountry };
/*     */   
/*     */ 
/*     */ 
/* 554 */   private static final String[] ADR_OTHER_FIELDS = { ContactConstants.A_otherStreet, ContactConstants.A_otherStreet, ContactConstants.A_otherStreet, ContactConstants.A_otherCity, ContactConstants.A_otherState, ContactConstants.A_otherPostalCode, ContactConstants.A_otherCountry };
/*     */   
/*     */ 
/*     */ 
/* 558 */   private static final String[] ORG_FIELDS = { ContactConstants.A_company, ContactConstants.A_department };
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   private static void decodeStructured(String value, String[] keys, Map<String, String> fields)
/*     */   {
/* 566 */     String suffix = "";
/* 567 */     int suffixInt = 1;
/*     */     boolean keyAvailable;
/*     */     do {
/* 570 */       keyAvailable = true;
/* 571 */       for (String key : keys) {
/* 572 */         String trialKey = key + suffix;
/* 573 */         if (fields.containsKey(trialKey)) {
/* 574 */           keyAvailable = false;
/* 575 */           break;
/*     */         }
/*     */       }
/* 578 */       if (!keyAvailable) {
/* 579 */         suffixInt++;
/* 580 */         suffix = String.valueOf(suffixInt);
/*     */       }
/* 582 */     } while ((!keyAvailable) && (suffixInt < 20));
/*     */     
/* 584 */     int i = 0;int start = 0;int f = 0; for (int len = value.length(); (i < len) && (f < keys.length); f++) {
/*     */       char c;
/* 586 */       for (boolean escaped = false; (i < len) && (((c = value.charAt(i)) != ';') || (escaped)); i++)
/* 587 */         escaped = (!escaped) && (c == '\\');
/* 588 */       if ((i > start) && (keys[f] != null)) {
/* 589 */         String keyToUse = keys[f] + suffix;
/* 590 */         fields.put(keyToUse, vcfDecode(value.substring(start, i)));
/*     */       }
/* 584 */       i++;start = i;
/*     */     }
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   private static String vcfDecode(String value)
/*     */   {
/* 596 */     if ((value == null) || (value.equals("")))
/* 597 */       return "";
/* 598 */     StringBuilder sb = new StringBuilder();
/* 599 */     boolean escaped = false;
/* 600 */     int i = 0; for (int len = value.length(); i < len; i++) {
/* 601 */       char c = value.charAt(i);
/* 602 */       if ((c == '\\') && (!escaped)) { escaped = true;
/* 603 */       } else if (!escaped) { sb.append(c);
/*     */       } else {
/* 605 */         if ((c == 'n') || (c == 'N')) { sb.append('\n');
/* 606 */         } else if ((c == 't') || (c == 'T')) sb.append('\t'); else
/* 607 */           sb.append(c);
/* 608 */         escaped = false;
/*     */       }
/*     */     }
/* 611 */     return sb.toString();
/*     */   }
/*     */   
/*     */   public static VCard formatContact(Contact con)
/*     */   {
/* 616 */     return formatContact(con, null, false);
/*     */   }
/*     */   
/*     */   public static VCard formatContact(Contact con, Collection<String> vcattrs, boolean includeXProps) {
/* 620 */     return formatContact(con, vcattrs, includeXProps, true);
/*     */   }
/*     */   
/*     */   public static VCard formatContact(Contact con, Collection<String> vcattrs, boolean includeXProps, boolean includeZimbraXProps) {
/* 624 */     Map<String, String> fields = con.getFields();
/* 625 */     List<Contact.Attachment> attachments = con.getAttachments();
/* 626 */     List<String> emails = con.getEmailAddresses(Contact.DerefGroupMembersOption.NONE);
/*     */     
/* 628 */     StringBuilder sb = new StringBuilder();
/* 629 */     sb.append("BEGIN:VCARD\r\n");
/*     */     
/*     */ 
/*     */ 
/*     */ 
/* 634 */     if ((vcattrs == null) || (vcattrs.contains("VERSION"))) {
/* 635 */       sb.append("VERSION:3.0\r\n");
/*     */     }
/*     */     
/* 638 */     String fn = (String)fields.get(ContactConstants.A_fullName);
/* 639 */     if ((vcattrs == null) || (vcattrs.contains("FN"))) {
/* 640 */       if ((fn == null) || (fn.trim().equals("")))
/* 641 */         try { fn = con.getFileAsString(); } catch (ServiceException e) { fn = ""; }
/* 642 */       if ((fn.trim().equals("")) && (!emails.isEmpty()))
/* 643 */         fn = (String)emails.get(0);
/* 644 */       if (fn.trim().equals("")) {
/* 645 */         String org = (String)fields.get(ContactConstants.A_company);
/* 646 */         if ((org != null) && (!org.trim().equals(""))) {
/* 647 */           fn = org;
/*     */         }
/*     */       }
/* 650 */       sb.append("FN:").append(vcfEncode(fn)).append("\r\n");
/*     */     }
/*     */     
/* 653 */     if ((vcattrs == null) || (vcattrs.contains("N"))) {
/* 654 */       StringBuilder nSb = new StringBuilder();
/* 655 */       nSb.append(vcfEncode((String)fields.get(ContactConstants.A_lastName))).append(';').append(vcfEncode((String)fields.get(ContactConstants.A_firstName))).append(';').append(vcfEncode((String)fields.get(ContactConstants.A_middleName))).append(';').append(vcfEncode((String)fields.get(ContactConstants.A_namePrefix))).append(';').append(vcfEncode((String)fields.get(ContactConstants.A_nameSuffix)));
/*     */       
/*     */ 
/*     */ 
/*     */ 
/* 660 */       String n = nSb.toString();
/*     */       
/*     */ 
/*     */ 
/* 664 */       if (";;;;".equals(n)) {
/* 665 */         n = vcfEncode(fn) + ";;;;";
/*     */       }
/* 667 */       sb.append("N:").append(n).append("\r\n");
/*     */     }
/*     */     
/* 670 */     if ((vcattrs == null) || (vcattrs.contains("NICKNAME")))
/* 671 */       encodeField(sb, "NICKNAME", (String)fields.get(ContactConstants.A_nickname));
/* 672 */     if ((vcattrs == null) || (vcattrs.contains("PHOTO")))
/* 673 */       encodeField(sb, "PHOTO;VALUE=URI", (String)fields.get(ContactConstants.A_image));
/* 674 */     if ((vcattrs == null) || (vcattrs.contains("BDAY"))) {
/* 675 */       String bday = (String)fields.get(ContactConstants.A_birthday);
/* 676 */       if (bday != null) {
/* 677 */         Date date = DateUtil.parseDateSpecifier(bday);
/* 678 */         if (date != null) {
/* 679 */           sb.append("BDAY;VALUE=date:").append(new SimpleDateFormat("yyyy-MM-dd").format(date)).append("\r\n");
/*     */         }
/*     */       }
/*     */     }
/* 683 */     if ((vcattrs == null) || (vcattrs.contains("ADR"))) {
/* 684 */       encodeAddress(sb, "home,postal,parcel", ContactConstants.A_homeStreet, ContactConstants.A_homeCity, ContactConstants.A_homeState, ContactConstants.A_homePostalCode, ContactConstants.A_homeCountry, 2, fields);
/*     */       
/*     */ 
/* 687 */       encodeAddress(sb, "work,postal,parcel", ContactConstants.A_workStreet, ContactConstants.A_workCity, ContactConstants.A_workState, ContactConstants.A_workPostalCode, ContactConstants.A_workCountry, 2, fields);
/*     */       
/*     */ 
/* 690 */       encodeAddress(sb, "postal,parcel", ContactConstants.A_otherStreet, ContactConstants.A_otherCity, ContactConstants.A_otherState, ContactConstants.A_otherPostalCode, ContactConstants.A_otherCountry, 2, fields);
/*     */     }
/*     */     
/*     */ 
/*     */ 
/* 695 */     if ((vcattrs == null) || (vcattrs.contains("TEL")))
/*     */     {
/* 697 */       encodePhone(sb, "car,voice", ContactConstants.A_carPhone, 2, fields);
/* 698 */       encodePhone(sb, "home,fax", ContactConstants.A_homeFax, 2, fields);
/* 699 */       encodePhone(sb, "home,voice", ContactConstants.A_homePhone, 2, fields);
/* 700 */       encodePhone(sb, "cell,voice", ContactConstants.A_mobilePhone, 2, fields);
/* 701 */       encodePhone(sb, "fax", ContactConstants.A_otherFax, 2, fields);
/* 702 */       encodePhone(sb, "voice", ContactConstants.A_otherPhone, 2, fields);
/* 703 */       encodePhone(sb, "pager", ContactConstants.A_pager, 2, fields);
/* 704 */       encodePhone(sb, "work,fax", ContactConstants.A_workFax, 2, fields);
/* 705 */       encodePhone(sb, "work,voice", ContactConstants.A_workPhone, 2, fields);
/*     */     }
/*     */     
/* 708 */     if ((vcattrs == null) || (vcattrs.contains("EMAIL"))) {
/* 709 */       encodeField(sb, "EMAIL;TYPE=internet", ContactConstants.A_email, false, 2, fields);
/* 710 */       encodeField(sb, "EMAIL;TYPE=internet", "workEmail", true, 1, fields);
/*     */     }
/*     */     
/* 713 */     if ((vcattrs == null) || (vcattrs.contains("URL"))) {
/* 714 */       encodeField(sb, "URL;TYPE=home", ContactConstants.A_homeURL, false, 2, fields);
/* 715 */       encodeField(sb, "URL", ContactConstants.A_otherURL, false, 2, fields);
/* 716 */       encodeField(sb, "URL;TYPE=work", ContactConstants.A_workURL, false, 2, fields);
/*     */     }
/*     */     
/* 719 */     if ((vcattrs == null) || (vcattrs.contains("ORG"))) {
/* 720 */       String org = (String)fields.get(ContactConstants.A_company);
/* 721 */       if ((org != null) && (!org.trim().equals(""))) {
/* 722 */         org = vcfEncode(org);
/* 723 */         String dept = (String)fields.get(ContactConstants.A_department);
/* 724 */         if ((dept != null) && (!dept.trim().equals(""))) {
/* 725 */           org = org + ';' + vcfEncode(dept);
/*     */         }
/* 727 */         sb.append("ORG:").append(org).append("\r\n");
/*     */       }
/*     */     }
/* 730 */     if ((vcattrs == null) || (vcattrs.contains("TITLE"))) {
/* 731 */       encodeField(sb, "TITLE", (String)fields.get(ContactConstants.A_jobTitle));
/*     */     }
/* 733 */     if ((vcattrs == null) || (vcattrs.contains("NOTE"))) {
/* 734 */       encodeField(sb, "NOTE", (String)fields.get(ContactConstants.A_notes));
/*     */     }
/* 736 */     if (((vcattrs == null) || (vcattrs.contains("PHOTO"))) && (attachments != null)) {
/* 737 */       for (Contact.Attachment attach : attachments) {
/*     */         try {
/* 739 */           if (attach.getName().equalsIgnoreCase(ContactConstants.A_image)) {
/* 740 */             String field = "PHOTO;ENCODING=B";
/* 741 */             if (attach.getContentType().startsWith("image/")) {
/*     */               try
/*     */               {
/* 744 */                 ContentType ct = new ContentType(attach.getContentType());
/* 745 */                 if (ct != null) {
/* 746 */                   String subType = ct.getSubType();
/* 747 */                   if (!Strings.isNullOrEmpty(subType)) {
/* 748 */                     field = field + ";TYPE=" + ct.getSubType().toUpperCase();
/*     */                   }
/*     */                 }
/*     */               }
/*     */               catch (ParseException e) {}
/*     */             }
/* 754 */             String encoded = new String(Base64.encodeBase64Chunked(attach.getContent())).trim().replace("\r\n", "\r\n ");
/* 755 */             sb.append(field).append(":\r\n ").append(encoded).append("\r\n");
/*     */           }
/*     */         } catch (OutOfMemoryError e) {
/* 758 */           Zimbra.halt("out of memory", e);
/*     */         } catch (Throwable t) {
/* 760 */           ZimbraLog.misc.info("error fetching attachment content: " + attach.getName(), t);
/*     */         }
/*     */       }
/*     */     }
/*     */     
/* 765 */     if ((vcattrs == null) || (vcattrs.contains("KEY"))) {
/* 766 */       String smimeCert = (String)fields.get(ContactConstants.A_userSMIMECertificate);
/* 767 */       if (smimeCert == null) {
/* 768 */         smimeCert = (String)fields.get(ContactConstants.A_userCertificate);
/*     */       }
/* 770 */       if (smimeCert != null) {
/* 771 */         smimeCert = smimeCert.trim().replace("\r\n", "\r\n ");
/* 772 */         String field = "KEY;ENCODING=B";
/* 773 */         sb.append(field).append(":\r\n ").append(smimeCert).append("\r\n");
/*     */       }
/*     */     }
/*     */     
/* 777 */     if ((vcattrs == null) || (vcattrs.contains("CATEGORIES"))) {
/* 778 */       String[] tags = con.getTags();
/* 779 */       if (tags.length > 0) {
/* 780 */         StringBuilder sbtags = new StringBuilder();
/* 781 */         for (String tagName : tags) {
/* 782 */           sbtags.append(sbtags.length() == 0 ? "" : ",").append(vcfEncode(tagName));
/*     */         }
/* 784 */         sb.append("CATEGORIES:").append(sbtags).append("\r\n");
/*     */       }
/*     */     }
/*     */     
/* 788 */     String uid = getUid(con);
/* 789 */     if ((vcattrs == null) || (vcattrs.contains("REV")))
/* 790 */       sb.append("REV:").append(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").format(new Date(con.getDate()))).append("\r\n");
/* 791 */     if ((vcattrs == null) || (vcattrs.contains("UID"))) {
/* 792 */       sb.append("UID:").append(uid).append("\r\n");
/*     */     }
/* 794 */     if (((vcattrs == null) && (includeZimbraXProps)) || ((vcattrs != null) && (vcattrs.contains("X-ZIMBRA-IMADDRESS")))) {
/* 795 */       encodeField(sb, "X-ZIMBRA-IMADDRESS", "imAddress", true, 1, fields);
/*     */     }
/* 797 */     if (((vcattrs == null) && (includeZimbraXProps)) || ((vcattrs != null) && (vcattrs.contains("X-ZIMBRA-ANNIVERSARY")))) {
/* 798 */       encodeField(sb, "X-ZIMBRA-ANNIVERSARY", ContactConstants.A_anniversary, false, 2, fields);
/*     */     }
/* 800 */     if (((vcattrs == null) && (includeZimbraXProps)) || ((vcattrs != null) && (vcattrs.contains("X-ZIMBRA-MAIDENNAME")))) {
/* 801 */       String maidenName = con.get(ContactConstants.A_maidenName);
/* 802 */       if (maidenName != null)
/* 803 */         sb.append("X-ZIMBRA-MAIDENNAME:").append(maidenName).append("\r\n");
/*     */     }
/* 805 */     if (includeXProps) {
/* 806 */       for (Map.Entry<String, String> xprop : con.getXProps().entrySet())
/*     */       {
/* 808 */         String key = (String)xprop.getKey();
/*     */         try {
/* 810 */           for (String value : Contact.parseMultiValueAttr((String)xprop.getValue())) {
/* 811 */             sb.append(key).append(":").append(value).append("\r\n");
/*     */           }
/*     */         } catch (JSONException e) {
/* 814 */           sb.append(key).append(":").append((String)xprop.getValue()).append("\r\n");
/*     */         }
/*     */       }
/*     */     }
/* 818 */     sb.append("END:VCARD\r\n");
/* 819 */     return new VCard(fn, sb.toString(), fields, attachments, uid);
/*     */   }
/*     */   
/*     */   public static String getUid(Contact con) {
/* 823 */     String uid = con.get("vcardUID");
/* 824 */     if (uid != null)
/* 825 */       return uid;
/* 826 */     return con.getMailbox().getAccountId() + ":" + con.getId();
/*     */   }
/*     */   
/*     */   public static String getUrl(Contact con) {
/* 830 */     String url = con.get("vcardURL");
/* 831 */     if (url != null)
/* 832 */       return url.replaceAll("/", "//");
/* 833 */     return getUid(con).replaceAll("/", "//");
/*     */   }
/*     */   
/*     */   private static void encodeField(StringBuilder sb, String name, String value) {
/* 837 */     if ((sb == null) || (name == null) || (value == null))
/* 838 */       return;
/* 839 */     sb.append(name).append(':').append(vcfEncode(value)).append("\r\n");
/*     */   }
/*     */   
/*     */   private static void encodeField(StringBuilder sb, String name, String firstKey, boolean skipFirstKey, int firstSuffix, Map<String, String> fields)
/*     */   {
/* 844 */     if ((sb == null) || (name == null)) {
/* 845 */       return;
/*     */     }
/*     */     
/* 848 */     if (!skipFirstKey) {
/* 849 */       String value = (String)fields.get(firstKey);
/* 850 */       if (value == null) {
/* 851 */         return;
/*     */       }
/* 853 */       sb.append(name).append(':').append(vcfEncode(value)).append("\r\n");
/*     */     }
/* 855 */     for (int suffix = firstSuffix; suffix < 20; suffix++) {
/* 856 */       String key = firstKey + String.valueOf(suffix);
/* 857 */       String value = (String)fields.get(key);
/* 858 */       if (value == null)
/* 859 */         return;
/* 860 */       sb.append(name).append(':').append(vcfEncode(value)).append("\r\n");
/*     */     }
/*     */   }
/*     */   
/*     */   private static void encodeAddress(StringBuilder sb, String type, String streetKey, String cityKey, String stateKey, String zipKey, String countryKey, int firstSuffix, Map<String, String> fields)
/*     */   {
/* 866 */     if ((sb == null) || (type == null))
/* 867 */       return;
/* 868 */     String street = (String)fields.get(streetKey);
/* 869 */     String city = (String)fields.get(cityKey);
/* 870 */     String state = (String)fields.get(stateKey);
/* 871 */     String zip = (String)fields.get(zipKey);
/* 872 */     String country = (String)fields.get(countryKey);
/*     */     
/* 874 */     if ((street == null) && (city == null) && (state == null) && (zip == null) && (country == null))
/* 875 */       return;
/* 876 */     String addr = ";;" + vcfEncode(street, true) + ';' + vcfEncode(city) + ';' + vcfEncode(state) + ';' + vcfEncode(zip) + ';' + vcfEncode(country);
/* 877 */     if (!addr.equals(";;;;;;")) {
/* 878 */       sb.append("ADR;TYPE=").append(type).append(':').append(addr).append("\r\n");
/*     */     }
/* 880 */     for (int suffix = firstSuffix; suffix < 20; suffix++) {
/* 881 */       String key = streetKey + String.valueOf(suffix);
/* 882 */       street = (String)fields.get(key);
/* 883 */       key = cityKey + String.valueOf(suffix);
/* 884 */       city = (String)fields.get(key);
/* 885 */       key = stateKey + String.valueOf(suffix);
/* 886 */       state = (String)fields.get(key);
/* 887 */       key = zipKey + String.valueOf(suffix);
/* 888 */       zip = (String)fields.get(key);
/* 889 */       key = countryKey + String.valueOf(suffix);
/* 890 */       country = (String)fields.get(key);
/* 891 */       if ((street == null) && (city == null) && (state == null) && (zip == null) && (country == null))
/* 892 */         return;
/* 893 */       addr = ";;" + vcfEncode(street, true) + ';' + vcfEncode(city) + ';' + vcfEncode(state) + ';' + vcfEncode(zip) + ';' + vcfEncode(country);
/* 894 */       if (!addr.equals(";;;;;;")) {
/* 895 */         sb.append("ADR;TYPE=").append(type).append(':').append(addr).append("\r\n");
/*     */       }
/*     */     }
/*     */   }
/*     */   
/*     */   private static void encodePhone(StringBuilder sb, String type, String firstKey, int firstSuffix, Map<String, String> fields) {
/* 901 */     if ((sb == null) || (type == null)) {
/* 902 */       return;
/*     */     }
/* 904 */     String phone = (String)fields.get(firstKey);
/* 905 */     if (phone == null)
/* 906 */       return;
/* 907 */     if (!phone.isEmpty())
/*     */     {
/* 909 */       sb.append("TEL;TYPE=").append(type).append(':').append(phone).append("\r\n");
/*     */     }
/* 911 */     for (int suffix = firstSuffix; suffix < 20; suffix++) {
/* 912 */       String key = firstKey + String.valueOf(suffix);
/* 913 */       phone = (String)fields.get(key);
/* 914 */       if (phone == null)
/* 915 */         return;
/* 916 */       if (!phone.isEmpty()) {
/* 917 */         sb.append("TEL;TYPE=").append(type).append(':').append(phone).append("\r\n");
/*     */       }
/*     */     }
/*     */   }
/*     */   
/*     */   private static String vcfEncode(String value) {
/* 923 */     return vcfEncode(value, false);
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   private static String vcfEncode(String value, boolean newlineToComma)
/*     */   {
/* 939 */     if ((value == null) || (value.equals("")))
/* 940 */       return "";
/* 941 */     StringBuilder sb = new StringBuilder();
/* 942 */     int i = 0; for (int len = value.length(); i < len; i++) {
/* 943 */       char c = value.charAt(i);
/* 944 */       if ((c == '\\') || (c == ',') || (c == ';')) {
/* 945 */         sb.append('\\').append(c);
/* 946 */       } else if (c == '\n') {
/* 947 */         sb.append(newlineToComma ? "," : "\\N");
/* 948 */       } else if ((c == '\t') || ((c >= ' ') && (c != '')))
/* 949 */         sb.append(c);
/*     */     }
/* 951 */     return sb.toString();
/*     */   }
/*     */   
/*     */   public String getFormatted() {
/* 955 */     return this.formatted;
/*     */   }
/*     */   
/*     */   public static void main(String[] args) throws ServiceException {
/* 959 */     parseVCard("BEGIN:VCARD\r\n\r\nFN\n :dr. john doe\nADR;HOME;WORK:;;Hambone Ltd.\\N5 Main St.;Charlotte;NC;24243\nEMAIL:foo@bar.con\nEMAIL:bar@goo.com\nN:doe;john;\\;\\\\;dr.;;;;\nEND:VCARD\n");
/* 960 */     parseVCard("BEGIN:VCARD\r\n\r\nFN\n :john doe\\, jr.\nORG:Zimbra;Marketing;Annoying Marketing\nA.TEL;type=fax,WORK:+1-800-555-1212\nTEL;type=home,work,voice:+1-800-555-1313\nNOTE;QUOTED-PRINTABLE:foo=3Dbar\nc.D.e.NOTE;ENCODING=B;charset=iso-8859-1:SWYgeW91IGNhbiByZWFkIHRoaXMgeW8=\nEND:VCARD\n");
/* 961 */     parseVCard("BEGIN : VCARD\nFN\n :john doe\\, jr.\nAGENT:\\nBEGIN:VCARD\\nEND:VCARD\nEND:VCARD");
/*     */   }
/*     */ }


/* Location:              /home/mint/zimbrastore.jar!/com/zimbra/cs/service/formatter/VCard.class
 * Java compiler version: 7 (51.0)
 * JD-Core Version:       0.7.1
 */